package spring.superrun.record.mvc.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.catalina.User;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.validator.constraints.Length;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import spring.superrun.record.mvc.attribute.AllowedAnyone;
import spring.superrun.record.mvc.attribute.Authorize;
import spring.superrun.record.mvc.di.SpringUtil;
import spring.superrun.record.mvc.dto.LocationVerityDto;
import spring.superrun.record.mvc.dto.ScanCodeRunRecordDto;
import spring.superrun.record.mvc.entity.SuperrunRecordranking;
import spring.superrun.record.mvc.entity.SuperrunRunrecords;
import spring.superrun.record.mvc.entity.enumlibs.ServiceResultCode;
import spring.superrun.record.mvc.entity.response.ServiceResult;
import spring.superrun.record.mvc.entity.response.ServiceResultOfT;
import spring.superrun.record.mvc.service.SuperrunRecordrankingService;
import spring.superrun.record.mvc.service.SuperrunRunrecordsService;
import org.springframework.web.bind.annotation.*;
import spring.superrun.record.mvc.setup.JWTConfig;
import spring.superrun.record.mvc.setup.RedisConfig;
import spring.superrun.tool.newid.Encrypt;
import spring.superrun.tool.newid.JwtUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * (SuperrunRunrecords)表控制层
 *
 * @author makejava
 * @since 2021-06-18 09:14:33
 */
@RestController
@Api(tags = "扫码打卡控制器")
@RequestMapping("/api/run_record")
public class SuperrunRunrecordsController {
    /**
     * 服务对象
     */
    @Resource
    private SuperrunRunrecordsService superrunRunrecordsService;
    @Resource
    private SuperrunRecordrankingService superrunRecordrankingService;
    private static final Log log = LogFactory.getLog(SuperrunRunrecordsController.class);
    private static Jedis jedis =SpringUtil.getBean("redisClient");
    @GetMapping("ranking")
    @AllowedAnyone
    public ResponseEntity<ServiceResultOfT<List<SuperrunRecordranking>>> GetUserRanking(){
        ServiceResultOfT<List<SuperrunRecordranking>> result
                = new ServiceResultOfT<>();
        result.IsFailed(ServiceResultCode.NotFound, "未找到统计排名记录");
        List<SuperrunRecordranking> ranking
                = superrunRecordrankingService.queryAllNoCondition("");
        result.setEntities(ranking);
        if (null==result.getEntities())
            return new ResponseEntity<>(result,HttpStatus.NOT_FOUND);
        result.IsSuccess("成功统计到排名记录");
        return new ResponseEntity<>(result,HttpStatus.OK);
    }
    @GetMapping("ranking/{uid}")
    @AllowedAnyone
    public ResponseEntity<ServiceResultOfT<List<SuperrunRecordranking>>> GetUsersRanking(@PathVariable String uid){
        ServiceResultOfT<List<SuperrunRecordranking>> result
                = new ServiceResultOfT<>();
        result.IsFailed(ServiceResultCode.NotFound, "未找到统计排名记录");
        List<SuperrunRecordranking> ranking
                = superrunRecordrankingService.queryAllNoCondition(uid);
        result.setEntities(ranking);
        if (null==result.getEntities())
            return new ResponseEntity<>(result,HttpStatus.NOT_FOUND);
        result.IsSuccess("成功统计到排名记录");
        return new ResponseEntity<>(result,HttpStatus.OK);
    }

    /**
     * 获取排名中平均速度的前几名默认前十
     * @return
     */
    @GetMapping("ranking/avgspeed_top")
    @AllowedAnyone
    public ResponseEntity<ServiceResultOfT<List<SuperrunRecordranking>>>
    GetAvgSpeedTopUserRanking(@RequestParam int n
            ,@RequestParam @Length(min = 0,max = 0,message = "性别只能输入一个字符")
                                      String sex
            ,@RequestParam @Length(min = 0,max = 20,message = "排序字段只能输入0到20个字母")
                                      String orderId)
    {
        if (n <= 0) n = 10;
        ServiceResultOfT<List<SuperrunRecordranking>>
                result = new ServiceResultOfT<>();
        result.IsFailed(ServiceResultCode.NotFound, "未找到统计排名记录");
        List<SuperrunRecordranking> query =
                superrunRecordrankingService.queryAllNoCondition("");
        result.setEntities(query);

        if (null==result.getEntities()||result.getEntities().size()<=0)
            return new ResponseEntity<>(result,HttpStatus.NOT_FOUND);
        if (null!=sex&&!sex.isEmpty()&&(sex.equals("男")||sex.equals("女")))
            query = query.stream().filter(q->q.getUser().getSex().equals(sex))
                    .collect(Collectors.toList());
        if (null!=orderId&&orderId.equals("seconds"))
            query.sort((q1,q2)->q2.getTotalseconds().compareTo(q1.getTotalseconds()));
        else
            query.sort((q1,q2)->q2.getTotalseconds().compareTo(q1.getTotalseconds()));

        if (query.size()>=n) result.setEntities(query.subList(0,n-1));
        else result.setEntities(query);

        if (null==result.getEntities())
            return new ResponseEntity<>(result,HttpStatus.NOT_FOUND);
        result.IsSuccess("成功统计到排名记录");
        return new ResponseEntity<>(result,HttpStatus.OK);
    }
    @GetMapping("{userId}")
    public ResponseEntity<ServiceResultOfT<List<SuperrunRunrecords>>>
                UserRunRecord(@PathVariable String userId, HttpServletRequest request){
        //从Token中获取UserId
        //String UserId = JwtUtils.GetUserId(request.getHeader(JWTConfig.Authorization));
        ServiceResultOfT<List<SuperrunRunrecords>> result = new ServiceResultOfT<>();
        result.IsFailed("获取该人的扫码记录失败!!!");
        if (userId.isEmpty()){
            log.error("获取失败，用户id为空");
            result.IsFailed(ServiceResultCode.NotFound,"记录失败，未认证!!!");
            return new ResponseEntity<>(result,HttpStatus.BAD_REQUEST);
        }
        List<SuperrunRunrecords> userRecords = superrunRunrecordsService
                                                    .GetUserRecords(userId);
        result.setEntities(userRecords);
        if (null!=result.getEntities()){
            result.IsSuccess("获取该用户的打卡记录成功!");
        }
        return new ResponseEntity<>(result
                ,result.Success?HttpStatus.OK:HttpStatus.BAD_REQUEST);
    }
    @Authorize
    @PostMapping("scan_run_record")
    public ResponseEntity<ServiceResult> ScanCodeRunRecord(@RequestBody ScanCodeRunRecordDto dto
            , HttpServletRequest request) throws Exception {
        //从Token中获取UserId
        String UserId = JwtUtils.GetUserId(request.getHeader(JWTConfig.Authorization));
        ServiceResult result = new ServiceResult();
        result.IsFailed("记录失败，请联系工作人员!!!");
        if (UserId.isEmpty()){
            log.error("记录失败，未认证!!!");
            result.IsFailed(ServiceResultCode.Unauthorized,"记录失败，未认证!!!");
            return new ResponseEntity<>(result,HttpStatus.UNAUTHORIZED);
        }
        //解密
        dto.setLocationId(Encrypt.decryptAES(dto.getLocationId()));
        if (dto.getLocationId().isEmpty())
        {
            log.error("位置信息异常,当前行为异常!!!");
            result.IsFailed(ServiceResultCode.KeyIsNull, "位置信息异常,当前行为异常!!!");
            return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST);
        }
        //验证该位置是否为合法位置
        ServiceResultOfT<LocationVerityDto> locationVerity = superrunRunrecordsService
                .RunRecordExistsAndVerityIsNextByLocationIdAsync(UserId, dto.getLocationId());

        if (!locationVerity.isSuccess())
        {
            result.IsFailed(locationVerity.getCode(),locationVerity.getMessage());
            return new ResponseEntity<>(result,HttpStatus.BAD_REQUEST);
        }
        //查询该用户的所有打卡记录根据完成时间做降序
        List<SuperrunRunrecords> userRunRecords
                =superrunRunrecordsService.GetUserRecords(UserId);
        userRunRecords.sort((r1,r2)->r2.getFinishtime().compareTo(r1.getFinishtime()));

        SuperrunRunrecords runRecord = new SuperrunRunrecords(
                new Date(),
                dto.getLocationId(),
                UserId,
                locationVerity.getEntities().getFromLastDistacnce()
        );
        runRecord.Add();
        if (userRunRecords.size()>0&&null!=userRunRecords.get(0))
        {
            //距离开始距离计算
            runRecord.setFromstartdistance(userRunRecords.stream()
                    .mapToDouble(SuperrunRunrecords::getFromlastdistance).sum()
                    +locationVerity.getEntities().getFromLastDistacnce());
            //所需秒数计算
            int second= (int)((runRecord.getFinishtime().getTime()-userRunRecords.get(0)
                    .getFinishtime().getTime())/(60 * 1000)%60);
            runRecord.setFromlasttimesecond(second);
            //平均速度
            double avgSpeed = locationVerity.getEntities().getFromLastDistacnce()
                    / runRecord.getFromlasttimesecond();
            runRecord.setAvgspeed(avgSpeed);
            //最快平均速度
            double maxSpeed = userRunRecords.stream()
                    .mapToDouble(SuperrunRunrecords::getAvgspeed).max().getAsDouble();
            runRecord.setMaxavgspeed(maxSpeed);
         }

        //添加该记录
        SuperrunRunrecords res = superrunRunrecordsService.insert(runRecord);
        if (null==res)
        {
            return new ResponseEntity<>(result,HttpStatus.BAD_REQUEST);
        };
        //生产者入队 将打卡记录id入队
        jedis.lpush(RedisConfig.RecordRankingQueueKey,res.getId());
        //.net core实现 await  _redisCommonService.EnQueueAsync(RedisKeyValues.RunRecordRankingQueueKey,runRecord.Id);
        result.IsSuccess("恭喜，扫码记录位置成功!!!");
        return new ResponseEntity<>(result,HttpStatus.OK);
    }
}
